<!DOCTYPE html>
 <html>
 <head>
   <meta charset="UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>数据可视化仪表盘</title>
   <script src="https://unpkg.com/vue@3"></script>
   <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
   <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
   <script src="https://unpkg.com/element-plus"></script>
   <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
   <style>
     body {
       margin: 0;
       padding: 0;
       font-family: Arial, sans-serif;
     }
     #app {
       display: flex;
       flex-direction: column;
       height: 100vh;
     }
     .header {
       display: flex;
       justify-content: space-between;
       align-items: center;
       padding: 0 20px;
       height: 60px;
       background-color: #409EFF;
       color: white;
       box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
     }
     .main-content {
       flex: 1;
       display: grid;
       grid-template-columns: repeat(3, 1fr);
       grid-template-rows: repeat(3, 1fr);
       gap: 10px;
       padding: 10px;
       overflow: auto;
     }
     .chart-container {
       background-color: #fff;
       border-radius: 4px;
       box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
       padding: 10px;
       position: relative;
     }
     .chart-loading {
       position: absolute;
       top: 0;
       left: 0;
       width: 100%;
       height: 100%;
       background-color: rgba(255, 255, 255, 0.7);
       display: flex;
       justify-content: center;
       align-items: center;
       z-index: 10;
     }
     .footer {
       height: 50px;
       background-color: #409EFF;
       color: white;
       display: flex;
       justify-content: center;
       align-items: center;
     }
     @media (max-width: 768px) {
       .main-content {
         grid-template-columns: repeat(2, 1fr);
       }
     }
     @media (max-width: 480px) {
       .main-content {
         grid-template-columns: 1fr;
       }
     }
   </style>
 </head>
 <body>
   <div id="app">
     <!-- 顶部导航 -->
     <div class="header">
       <div class="header-left">
         <h2>数据可视化仪表盘</h2>
       </div>
       <div class="header-right">
         <el-dropdown>
           <span class="el-dropdown-link">
             菜单 <i class="el-icon-arrow-down el-icon--right"></i>
           </span>
           <template #dropdown>
             <el-dropdown-menu>
               <el-dropdown-item @click="refreshCharts">刷新数据</el-dropdown-item>
               <el-dropdown-item>设置</el-dropdown-item>
               <el-dropdown-item divided>退出登录</el-dropdown-item>
             </el-dropdown-menu>
           </template>
         </el-dropdown>
       </div>
     </div>

     <!-- 主内容区 - 9宫格图表 -->
     <div class="main-content">
       <!-- 线图 -->
       <div class="chart-container" ref="chart1">
         <div v-if="loading.chart1" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 柱状图 -->
       <div class="chart-container" ref="chart2">
         <div v-if="loading.chart2" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 饼图 -->
       <div class="chart-container" ref="chart3">
         <div v-if="loading.chart3" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 散点图 -->
       <div class="chart-container" ref="chart4">
         <div v-if="loading.chart4" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 雷达图 -->
       <div class="chart-container" ref="chart5">
         <div v-if="loading.chart5" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 仪表盘 -->
       <div class="chart-container" ref="chart6">
         <div v-if="loading.chart6" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 漏斗图 -->
       <div class="chart-container" ref="chart7">
         <div v-if="loading.chart7" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 热力图 -->
       <div class="chart-container" ref="chart8">
         <div v-if="loading.chart8" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>

       <!-- 主题河流图 -->
       <div class="chart-container" ref="chart9">
         <div v-if="loading.chart9" class="chart-loading">
           <el-spinner type="el-icon-loading"></el-spinner>
         </div>
       </div>
     </div>

     <!-- 底部版权信息 -->
     <div class="footer">
       <span>© 2023 数据可视化仪表盘. 保留所有权利.</span>
     </div>
   </div>

   <script>
     const App = {
       data() {
         return {
           charts: [],
           loading: {
             chart1: true,
             chart2: true,
             chart3: true,
             chart4: true,
             chart5: true,
             chart6: true,
             chart7: true,
             chart8: true,
             chart9: true
           },
           error: {}
         };
       },
       mounted() {
         this.fetchAllChartData();
       },
       methods: {
         // 统一获取所有图表数据
         async fetchAllChartData() {
           // 修改为本地Flask服务器地址
           const apiBase = 'http://localhost:5000/api/charts';

           try {
             // 并行请求所有图表数据
             const [
               lineChartData,
               barChartData,
               pieChartData,
               scatterChartData,
               radarChartData,
               gaugeChartData,
               funnelChartData,
               heatmapChartData,
               themeRiverChartData
             ] = await Promise.all([
               this.fetchChartData(`${apiBase}/line`),
               this.fetchChartData(`${apiBase}/bar`),
               this.fetchChartData(`${apiBase}/pie`),
               this.fetchChartData(`${apiBase}/scatter`),
               this.fetchChartData(`${apiBase}/radar`),
               this.fetchChartData(`${apiBase}/gauge`),
               this.fetchChartData(`${apiBase}/funnel`),
               this.fetchChartData(`${apiBase}/heatmap`),
               this.fetchChartData(`${apiBase}/theme-river`)
             ]);

             // 初始化所有图表
             this.initChart1(lineChartData);
             this.initChart2(barChartData);
             this.initChart3(pieChartData);
             this.initChart4(scatterChartData);
             this.initChart5(radarChartData);
             this.initChart6(gaugeChartData);
             this.initChart7(funnelChartData);
             this.initChart8(heatmapChartData);
             this.initChart9(themeRiverChartData);

           } catch (error) {
             console.error('获取图表数据失败:', error);
             // 显示错误信息
             Object.keys(this.loading).forEach(key => {
               this.error[key] = '加载数据失败，请刷新重试';
             });
           }
         },

         // 通用数据获取方法
         async fetchChartData(url) {
           try {
             const response = await axios.get(url);
             return response.data;
           } catch (error) {
             console.error(`获取图表数据失败 (${url}):`, error);
             throw error;
           }
         },

         // 初始化线图
         initChart1(data) {
           const chart = echarts.init(this.$refs.chart1);
           chart.setOption({
             title: { text: '线图' },
             tooltip: {},
             xAxis: {
               type: 'category',
               data: data.xAxis || []
             },
             yAxis: {},
             series: [{
               name: data.seriesName || '数据',
               type: 'line',
               data: data.seriesData || [],
               smooth: true
             }]
           });
           this.charts.push(chart);
           this.loading.chart1 = false;

           // 窗口大小变化时重绘图表
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化柱状图
         initChart2(data) {
           const chart = echarts.init(this.$refs.chart2);
           chart.setOption({
             title: { text: '柱状图' },
             tooltip: {},
             xAxis: {
               type: 'category',
               data: data.xAxis || []
             },
             yAxis: {},
             series: [{
               name: data.seriesName || '数据',
               type: 'bar',
               data: data.seriesData || [],
               itemStyle: {
                 color: '#409EFF'
               }
             }]
           });
           this.charts.push(chart);
           this.loading.chart2 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化饼图
         initChart3(data) {
           const chart = echarts.init(this.$refs.chart3);
           chart.setOption({
             title: { text: '饼图' },
             tooltip: {
               trigger: 'item',
               formatter: '{a} <br/>{b}: {c} ({d}%)'
             },
             legend: {
               type: 'scroll',
               orient: 'vertical',
               right: 10,
               top: 20,
               bottom: 20,
               data: data.legendData || []
             },
             series: [{
               name: data.seriesName || '数据',
               type: 'pie',
               radius: ['40%', '70%'],
               avoidLabelOverlap: false,
               label: {
                 show: true,
                 formatter: '{b}: {d}%'
               },
               data: data.seriesData || []
             }]
           });
           this.charts.push(chart);
           this.loading.chart3 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化散点图
         initChart4(data) {
           const chart = echarts.init(this.$refs.chart4);
           chart.setOption({
             title: { text: '散点图' },
             tooltip: {},
             xAxis: {},
             yAxis: {},
             series: [{
               symbolSize: 20,
               data: data.seriesData || [],
               type: 'scatter'
             }]
           });
           this.charts.push(chart);
           this.loading.chart4 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化雷达图
         initChart5(data) {
           const chart = echarts.init(this.$refs.chart5);
           chart.setOption({
             title: { text: '雷达图' },
             legend: {
               data: data.legendData || []
             },
             radar: {
               indicator: data.indicators || []
             },
             series: [{
               name: data.seriesName || '数据',
               type: 'radar',
               data: data.seriesData || []
             }]
           });
           this.charts.push(chart);
           this.loading.chart5 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化仪表盘
         initChart6(data) {
           const chart = echarts.init(this.$refs.chart6);
           chart.setOption({
             title: { text: '仪表盘' },
             series: [{
               type: 'gauge',
               progress: {
                 show: true,
                 width: 18
               },
               axisLine: {
                 lineStyle: {
                   width: 18
                 }
               },
               detail: {
                 valueAnimation: true,
                 fontSize: 20,
                 offsetCenter: [0, '70%']
               },
               data: [{
                 value: data.value || 0,
                 name: data.name || '指标'
               }]
             }]
           });
           this.charts.push(chart);
           this.loading.chart6 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化漏斗图
         initChart7(data) {
           const chart = echarts.init(this.$refs.chart7);
           chart.setOption({
             title: { text: '漏斗图' },
             tooltip: {
               trigger: 'item',
               formatter: '{a} <br/>{b} : {c}%'
             },
             legend: {
               data: data.legendData || []
             },
             series: [{
               name: data.seriesName || '漏斗',
               type: 'funnel',
               left: '10%',
               top: 60,
               bottom: 60,
               width: '80%',
               min: 0,
               max: 100,
               minSize: '0%',
               maxSize: '100%',
               sort: 'descending',
               gap: 2,
               label: {
                 show: true,
                 position: 'inside'
               },
               data: data.seriesData || []
             }]
           });
           this.charts.push(chart);
           this.loading.chart7 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化热力图
         initChart8(data) {
           const chart = echarts.init(this.$refs.chart8);
           chart.setOption({
             title: { text: '热力图' },
             tooltip: {
               position: 'top'
             },
             grid: {
               height: '80%',
               top: '10%'
             },
             xAxis: {
               type: 'category',
               data: data.xAxis || [],
               splitArea: {
                 show: true
               }
             },
             yAxis: {
               type: 'category',
               data: data.yAxis || [],
               splitArea: {
                 show: true
               }
             },
             visualMap: {
               min: data.minValue || 0,
               max: data.maxValue || 10,
               calculable: true,
               orient: 'horizontal',
               left: 'center',
               bottom: '0%'
             },
             series: [{
               name: data.seriesName || '数据',
               type: 'heatmap',
               data: data.seriesData || [],
               label: {
                 show: false
               }
             }]
           });
           this.charts.push(chart);
           this.loading.chart8 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 初始化主题河流图
         initChart9(data) {
           const chart = echarts.init(this.$refs.chart9);
           chart.setOption({
             title: { text: '主题河流图' },
             tooltip: {
               trigger: 'axis',
               axisPointer: {
                 type: 'line',
                 lineStyle: {
                   color: 'rgba(0,0,0,0.2)',
                   width: 1,
                   type: 'solid'
                 }
               }
             },
             legend: {
               data: data.legendData || []
             },
             singleAxis: {
               top: 50,
               bottom: 50,
               axisTick: {},
               axisLabel: {},
               type: 'time',
               axisPointer: {
                 animation: true,
                 label: {
                   show: true
                 }
               },
               splitLine: {
                 show: true,
                 lineStyle: {
                   type: 'dashed',
                   opacity: 0.2
                 }
               }
             },
             series: [{
               type: 'themeRiver',
               emphasis: {
                 itemStyle: {
                   shadowBlur: 20,
                   shadowColor: 'rgba(0, 0, 0, 0.8)'
                 }
               },
               data: data.seriesData || []
             }]
           });
           this.charts.push(chart);
           this.loading.chart9 = false;
           window.addEventListener('resize', () => chart.resize());
         },

         // 刷新所有图表
         refreshCharts() {
           // 重置加载状态
           Object.keys(this.loading).forEach(key => {
             this.loading[key] = true;
             this.error[key] = null;
           });

           // 销毁现有图表
           this.charts.forEach(chart => chart.dispose());
           this.charts = [];

           // 重新获取数据
           this.fetchAllChartData();
         }
       },
       beforeUnmount() {
         // 清理图表实例和事件监听器
         this.charts.forEach(chart => {
           window.removeEventListener('resize', () => chart.resize());
           chart.dispose();
         });
       }
     };

     const app = Vue.createApp(App);
     app.use(ElementPlus);
     app.mount("#app");
   </script>
 </body>
 </html>